/**
* Copyright 2009, Jethro Grassie, Creative Jar Technology Ltd (http://www.cjtech.co.uk)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
**/

package com.adobe.cairngorm.business;

import javafx.async.RunnableFuture;
import com.sun.javafx.runtime.Entry;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.Remote;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;

import java.util.List;
import java.util.ArrayList;


public class RMIRunnable implements RunnableFuture
{
    private RMICallInfo callInfo;
    private RMIListener listener;

    public RMIRunnable(RMICallInfo callInfo, RMIListener listener) throws Exception
    {
        this.callInfo = callInfo;
        this.listener = listener;
    }

    public void run() throws Exception
    {
        // Do RMI calls here and post result.
        if(System.getSecurityManager() == null)
        {
            System.setSecurityManager(new SecurityManager());
        }
        Registry registry = LocateRegistry.getRegistry(callInfo.getHost());
        Remote remoteObject = registry.lookup(callInfo.getLookupName());
        Class clazz = remoteObject.getClass();
        List paramTypes = null;
        for(int i=0; i<callInfo.getMethodParameters().size(); i++)
        {
            if(paramTypes == null)
                paramTypes = new ArrayList();
            paramTypes.add(callInfo.getMethodParameters().get(i).getClass());
        }

        Class[] parameterClasses = null;
        if(paramTypes != null)
            parameterClasses = (Class[]) paramTypes.toArray();

        Method methodToCall = clazz.getMethod(callInfo.getMethodName(), parameterClasses);

        if(methodToCall != null)
        {
            Object returned = methodToCall.invoke(remoteObject,
                callInfo.getMethodParameters().toArray());
            postResult(returned);
        }
    }
    
    private void postResult(final Object data)
    {
        Entry.deferAction(
            new Runnable()
            {
                public void run()
                {
                    listener.onResult(data);
                }
            }
        );
    }
}
